#include "HistoryDataEngine.h"
#include "LogManager.h"
#include "Core/Redis/RedisWrapper.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDateTime>
#include <QRegularExpression>
#include <fmt/format.h>
#include <set>
#include <sstream>
#include <vector>
#include <string>
#include <algorithm>

namespace Market {

HistoryDataEngine::HistoryDataEngine(QObject* parent) 
    : QObject(parent)
    , m_networkManager(new QNetworkAccessManager(this)) {
    
    connect(m_networkManager, &QNetworkAccessManager::finished,
            this, &HistoryDataEngine::handleNetworkReply);
            
    connect(&m_retryTimer, &QTimer::timeout,
            this, &HistoryDataEngine::retryFailedRequest);
            
    m_retryTimer.setInterval(5000);  // 5秒后重试
}

HistoryDataEngine::~HistoryDataEngine() {
    stopSync();
}

bool HistoryDataEngine::init() {
    if (!m_networkManager) {
        MLOG_ERROR("history", "Failed to create network manager");
        return false;
    }
    
    MLOG_INFO("history", "HistoryDataEngine initialized");
    return true;
}

void HistoryDataEngine::addContract(const std::string& symbol, const std::string& exchg) {
    for (const auto& period : m_periods) {
        BarRequest request;
        request.symbol = symbol;
        request.exchg = exchg;
        request.period = period;
        
        // 设置回调函数
        request.callback = [this, symbol, exchg, period](const WTSBarStruct& bar) {
            // 构造Redis key
            std::string key = fmt::format("{}:{}:{}", exchg, symbol, static_cast<int>(period));
            // 保存到Redis
            saveToRedis(key, bar, bar.time);
        };
        
        m_requestQueue.enqueue(request);
        m_totalRequests++;
    }
    
    MLOG_INFO("history", "Added contract {} to sync queue", symbol);
}

void HistoryDataEngine::startSync() {
    if (m_requestQueue.isEmpty()) {
        MLOG_WARN("history", "No contracts to sync");
        return;
    }
    
    m_syncCompleted = false;
    processNextRequest();
    
    MLOG_INFO("history", "Started history data sync");
}

void HistoryDataEngine::stopSync() {
    for (auto reply : m_replies) {
        if (reply) {
            reply->abort();
            reply->deleteLater();
        }
    }
    m_replies.clear();
    
    m_retryTimer.stop();
    m_requestQueue.clear();
    m_failedRequests.clear();
    
    MLOG_INFO("history", "Stopped history data sync");
}

QString HistoryDataEngine::convertSymbol(const std::string& symbol, const std::string& exchg) {
    QString qsymbol = QString::fromStdString(symbol);
    
    // 提取品种代码和月份
    QRegularExpression re("([A-Za-z]+)(\\d{3,4})");
    auto match = re.match(qsymbol);
    if (!match.hasMatch()) {
        MLOG_ERROR("history", "Invalid contract code format: {}", symbol);
        return qsymbol;
    }
    
    QString product = match.captured(1);  // 品种代码
    QString month = match.captured(2);    // 月份部分
    
    // 郑商所合约特殊处理
    if (exchg == "CZCE" && month.length() == 3) {
        product = product.toUpper();  // 品种代码大写
        month = "2" + month;  // 在三位数字前加2
    }
    
    QString result = product + month;
    MLOG_DEBUG("history", "Convert contract code: {} -> {}", symbol, result.toStdString());
    return result;
}

QString HistoryDataEngine::buildUrl(const BarRequest& request) {
    QString symbol = convertSymbol(request.symbol, request.exchg);
    
    if (request.period == TrPeriod::Day) {
        return QString("https://stock2.finance.sina.com.cn/futures/api/jsonp.php/=/InnerFuturesNewService.getDailyKLine?symbol=%1")
            .arg(symbol);
    } else {
        // 使用TrPeriod的枚举值作为type
        int type = static_cast<int>(request.period);
        
        return QString("https://stock2.finance.sina.com.cn/futures/api/jsonp.php/=/InnerFuturesNewService.getFewMinLine?symbol=%1&type=%2")
            .arg(symbol).arg(type);
    }
}

void HistoryDataEngine::handleNetworkReply(QNetworkReply* reply) {
    reply->deleteLater();
    m_activeRequests--;
    
    QString url = reply->url().toString();
    
    // 获取对应的请求
    if (!m_pendingRequests.contains(url)) {
        MLOG_ERROR("history", "No matching request found for URL: {}", url.toStdString());
        return;
    }
    
    BarRequest request = m_pendingRequests.take(url);
    
    if (reply->error() != QNetworkReply::NoError) {
        MLOG_ERROR("history", "Network error: {} - URL: {}", 
            reply->errorString().toStdString(), url.toStdString());
        handleRequestFailure(reply->url());
        return;
    }
    
    QByteArray data = reply->readAll();
    QString strData = QString::fromUtf8(data);
    
    // 去掉JSONP包装
    if (strData.startsWith("/*<script>") && strData.endsWith(");")) {
        strData = strData.mid(51, strData.size() - 53);
    } else {
        MLOG_ERROR("history", "Unexpected data format: {}", strData.toStdString());
        handleRequestFailure(reply->url());
        return;
    }
    
    // 解析数据
    bool success = false;
    if (request.period == TrPeriod::Day) {
        success = parseDailyData(strData.toUtf8(), request);
    } else {
        success = parseMinuteData(strData.toUtf8(), request);
    }
    
    if (!success) {
        handleRequestFailure(reply->url());
        return;
    }
    
    // 更新进度
    m_completedRequests++;
    emit progressUpdated(m_completedRequests, m_totalRequests);
    
    // 检查数据完整性
    checkDataIntegrity(request);
    
    // 处理下一个请求
    m_replies.remove(url);
    processNextRequest();
}

void HistoryDataEngine::handleRequestFailure(const QUrl& url) {
    QString urlStr = url.toString();
    
    // 从待处理请求中获取失败的请求
    if (!m_pendingRequests.contains(urlStr)) {
        MLOG_ERROR("history", "No matching request found for failed URL: {}", urlStr.toStdString());
        return;
    }
    
    BarRequest failedRequest = m_pendingRequests.take(urlStr);
    m_currentRetries++;
    
    if (m_currentRetries < m_maxRetries) {
        failedRequest.isRetry = true;
        m_failedRequests.enqueue(failedRequest);
        if (!m_retryTimer.isActive()) {
            m_retryTimer.start();
        }
        MLOG_WARN("history", "Request failed, will retry: {}", urlStr.toStdString());
    } else {
        MLOG_ERROR("history", "Request failed after {} retries: {}", 
            m_maxRetries, urlStr.toStdString());
        emit syncFailed(QString("Failed to sync data for %1")
            .arg(QString::fromStdString(failedRequest.symbol)));
    }
}

bool HistoryDataEngine::parseMinuteData(const QByteArray& data, const BarRequest& request) {
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(data, &error);
    
    if (error.error != QJsonParseError::NoError) {
        MLOG_ERROR("history", "Failed to parse minute data: {}", error.errorString().toStdString());
        return false;
    }
    
    if (!doc.isArray()) {
        MLOG_ERROR("history", "Expected JSON array");
        return false;
    }
    
    QJsonArray arr = doc.array();
    for (const auto& item : arr) {
        QJsonObject obj = item.toObject();
        
        // 解析时间
        QString timeStr = obj["d"].toString();
        QDateTime datetime = QDateTime::fromString(timeStr, "yyyy-MM-dd HH:mm:ss");
        
        if (!datetime.isValid()) {
            MLOG_ERROR("history", "Invalid datetime format: {}", timeStr.toStdString());
            continue;  // 跳过无效数据，继续处理
        }
        
        // 创建Bar结构
        WTSBarStruct bar{};
        bar.time = datetime.toSecsSinceEpoch();
        bar.date = datetime.date().year() * 10000 + 
                  datetime.date().month() * 100 + 
                  datetime.date().day();
                  
        // 解析价格和成交量
        bar.open = obj["o"].toString().toDouble();
        bar.high = obj["h"].toString().toDouble();
        bar.low = obj["l"].toString().toDouble();
        bar.close = obj["c"].toString().toDouble();
        bar.vol = obj["v"].toString().toInt();
        
        // 调用回调函数
        if (request.callback) {
            request.callback(bar);
        }
    }
    
    return true;
}

bool HistoryDataEngine::parseDailyData(const QByteArray& data, const BarRequest& request) {
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(data, &error);
    
    if (error.error != QJsonParseError::NoError) {
        MLOG_ERROR("history", "Failed to parse daily data: {}", error.errorString().toStdString());
        return false;
    }
    
    if (!doc.isArray()) {
        MLOG_ERROR("history", "Expected JSON array");
        return false;
    }
    
    QJsonArray arr = doc.array();
    for (const auto& item : arr) {
        QJsonObject obj = item.toObject();
        
        // 解析日期
        QString dateStr = obj["d"].toString();
        QDate date = QDate::fromString(dateStr, "yyyy-MM-dd");
        QDateTime datetime(date, QTime(15, 0, 0));  // 使用收盘时间
        
        // 创建Bar结构
        WTSBarStruct bar{};
        bar.time = datetime.toSecsSinceEpoch();
        bar.date = date.year() * 10000 + date.month() * 100 + date.day();
        
        // 解析价格和成交量
        bar.open = obj["o"].toString().toDouble();
        bar.high = obj["h"].toString().toDouble();
        bar.low = obj["l"].toString().toDouble();
        bar.close = obj["c"].toString().toDouble();
        bar.vol = obj["v"].toString().toInt();
        
        // 调用回调函数
        if (request.callback) {
            request.callback(bar);
        }
    }
    
    return true;
}

void HistoryDataEngine::saveToRedis(const std::string& key, const WTSBarStruct& bar, double score) {
    try {
        std::string value = fmt::format("{}:{}:{}:{}:{}:{}:{}",
            bar.time, bar.open, bar.high, bar.low, bar.close,
            bar.vol, bar.interest);
        
        // 保存到Redis的SortedSet
        REDIS_WRAPPER->getRedis()->zadd(key, value, score);
        
        MLOG_DEBUG("history", "Saved bar data to Redis: key={}, time={}", 
            key, bar.time);
    } catch (const std::exception& e) {
        MLOG_ERROR("history", "Failed to save bar data to Redis: {}", e.what());
    }
}

void HistoryDataEngine::checkDataIntegrity(const BarRequest& request) {
    try {
        // 构造Redis key直���使用枚举值
        std::string key = fmt::format("{}:{}:{}", request.exchg, request.symbol, static_cast<int>(request.period));
        std::vector<std::string> existingData;
        REDIS_WRAPPER->getRedis()->zrange(key, 0, -1, std::back_inserter(existingData));

        // 检查数据连续性
        std::vector<int64_t> timestamps;
        for (const auto& data : existingData) {
            std::istringstream iss(data);
            std::string timeStr;
            if (std::getline(iss, timeStr, ':')) {
                timestamps.push_back(std::stoll(timeStr));
            }
        }

        // 按时间排序
        std::sort(timestamps.begin(), timestamps.end());

        // 检查时间间隔
        int64_t expectedInterval = 0;
        switch (request.period) {
            case TrPeriod::M1: expectedInterval = 60; break;
            case TrPeriod::M3: expectedInterval = 180; break;
            case TrPeriod::M5: expectedInterval = 300; break;
            case TrPeriod::M10: expectedInterval = 600; break;
            case TrPeriod::M15: expectedInterval = 900; break;
            case TrPeriod::M30: expectedInterval = 1800; break;
            case TrPeriod::H1: expectedInterval = 3600; break;
            case TrPeriod::H2: expectedInterval = 7200; break;
            case TrPeriod::Day: expectedInterval = 86400; break;
            default:
                MLOG_ERROR("history", "Unknown period type: {}", static_cast<int>(request.period));
                return;
        }

        // 检查数据间隔并记录缺口
        std::vector<std::pair<int64_t, int64_t>> gaps;
        for (size_t i = 1; i < timestamps.size(); ++i) {
            int64_t interval = timestamps[i] - timestamps[i-1];
            if (interval > expectedInterval) {
                gaps.push_back({timestamps[i-1], timestamps[i]});
            }
        }

        // 报告数据统计
        MLOG_INFO("history", "Total records for {}: {}", key, timestamps.size());
        if (!timestamps.empty()) {
            QDateTime first = QDateTime::fromSecsSinceEpoch(timestamps.front());
            QDateTime last = QDateTime::fromSecsSinceEpoch(timestamps.back());
            MLOG_DEBUG("history", "Data range: {} to {}, {}", 
                first.toString("yyyy-MM-dd HH:mm:ss").toStdString(),
                last.toString("yyyy-MM-dd HH:mm:ss").toStdString(),
                static_cast<int>(request.period));
        }

        // 如果发现数据缺口，重新请求数据
        if (!gaps.empty()) {
            MLOG_INFO("history", "Found {} data gaps in {}", gaps.size(), key);
            for (const auto& gap : gaps) {
                QDateTime start = QDateTime::fromSecsSinceEpoch(gap.first);
                QDateTime end = QDateTime::fromSecsSinceEpoch(gap.second);
                // MLOG_INFO("history", "Requesting data for gap from {} to {}", 
                //     start.toString("yyyy-MM-dd HH:mm:ss").toStdString(),
                //     end.toString("yyyy-MM-dd HH:mm:ss").toStdString());
                
                // TODO: 实现请求缺失数据的逻辑
                // requestHistoryData(request, gap.first, gap.second);
            }
        }
    }
    catch (const std::exception& e) {
        MLOG_ERROR("history", "Error checking data integrity: {}", e.what());
    }
}

void HistoryDataEngine::processNextRequest() {
    if (m_activeRequests < m_maxConcurrentRequests && !m_requestQueue.isEmpty()) {
        BarRequest request = m_requestQueue.dequeue();
        QString url = buildUrl(request);
        request.url = url;  // 保存URL用于后续匹配
        
        QNetworkRequest networkRequest(url);
        // 添加必要的请求头
        networkRequest.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0");
        networkRequest.setRawHeader("Referer", "https://finance.sina.com.cn");
        networkRequest.setRawHeader("Accept", "application/json");
        
        QNetworkReply* reply = m_networkManager->get(networkRequest);
        m_replies.insert(url, reply);
        m_pendingRequests.insert(url, request);  // 保存请求信息
        m_activeRequests++;
        
        MLOG_DEBUG("history", "Processing request: {}", url.toStdString());
        
        // 在请求之间添加时间间隔
        QTimer::singleShot(1000, this, &HistoryDataEngine::processNextRequest);
    }
    
    if (m_requestQueue.isEmpty() && m_activeRequests == 0 && m_failedRequests.isEmpty()) {
        m_syncCompleted = true;
        emit syncCompleted();
        MLOG_DEBUG("history", "History data sync completed");
    }
}

void HistoryDataEngine::retryFailedRequest() {
    if (m_failedRequests.isEmpty()) {
        m_retryTimer.stop();
        return;
    }
    
    if (m_activeRequests < m_maxConcurrentRequests) {
        BarRequest request = m_failedRequests.dequeue();
        QString url = buildUrl(request);
        request.url = url;  // 更新URL
        
        QNetworkRequest networkRequest(url);
        networkRequest.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0");
        networkRequest.setRawHeader("Referer", "https://finance.sina.com.cn");
        networkRequest.setRawHeader("Accept", "application/json");
        
        QNetworkReply* reply = m_networkManager->get(networkRequest);
        m_replies.insert(url, reply);
        m_pendingRequests.insert(url, request);  // 保存请求信息
        m_activeRequests++;
        
        MLOG_TRACE("history", "Retrying request: {}", url.toStdString());
    }
}

} // namespace Market 